package cobolinfo;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class FileControler {
	private String mBasePath = "files";
	private String mCobolPath = this.mBasePath + "\\Cobol";
	private String mJclPath = this.mBasePath + "\\Jcl";
	private String mCodePath = this.mBasePath + "\\Codes";
	protected String mHistoryPath = this.mBasePath + "\\History.txt";
	private HashMap<String, String> mCobolFiles = new HashMap<String, String>();
	private HashMap<String, String> mJclFiles = new HashMap<String, String>();
	private HashMap<String, String> mCodeFiles = new HashMap<String, String>();
	private String mSimpleComment = "*$$";
	private String mMultiCommentStart = "*$%";
	private String mMultiCommentEnd = "*%$";
	public static String mSeparator = "\t";
	private HashMap<ArrayList<Integer>, String> mComments = new HashMap<ArrayList<Integer>, String>();
	private HashMap<String, HashMap<String, String>> mCodes = new HashMap<String, HashMap<String, String>>();

	public FileControler() {
		this.mCobolFiles = new HashMap<String, String>();
	}

	public ArrayList<String> GetCobolFiles() {
		String path = this.mCobolPath;
		File dir = new File(path);
		String[] children = dir.list();
		ArrayList<String> names = new ArrayList<String>();
		for (String cname : children) {
			String fpath = path + "\\" + cname;
			this.mCobolFiles.put(cname, fpath);
			names.add(cname);
		}
		return names;
	}

	public ArrayList<String> GetCodeFiles() {
		String path = this.mCodePath;
		File dir = new File(path);
		String[] children = dir.list();
		ArrayList<String> names = new ArrayList<String>();
		for (String cname : children) {
			String fpath = path + "\\" + cname;
			this.mCodeFiles.put(cname, fpath);
			names.add(cname);
		}
		this.ParseCodes();
		return names;
	}

	private void ParseCodes() {
		Iterator iterator = this.mCodeFiles.keySet().iterator();

		while (iterator.hasNext()) {
			String cname = iterator.next().toString();
			String path = this.mCodeFiles.get(cname);

			this.ParseCodeFile(cname, path);
		}
	}

	private void ParseCodeFile(String cname, String path) {
		HashMap<String, String> hash = new HashMap<String, String>();
		ArrayList<String> lines = this.ReadFile(path, false);
		for (String line : lines) {
			if (line.length() > 0) {
				int l = line.indexOf("=");
				String num = line.substring(0, l);
				String text = line.substring(l + 1, line.length());
				hash.put(num, text);
			}
		}
		this.mCodes.put(cname, hash);
	}

	private String ParseCadena(String cad) {
		String result = "";
		if (cad.length() >= 7) {
			int max = 72;
			if (cad.length() < 72) {
				max = cad.length();
			}
			result = cad.substring(6, max);
		}
		return result;
	}

	protected ArrayList<String> ReadFile(String path) {
		return this.ReadFile(path, true);
	}

	protected void WriteFile(String path, String text) {
		try {
			FileWriter fstream = new FileWriter(path, true);
			BufferedWriter out = new BufferedWriter(fstream);
			out.write(text);
			out.close();
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}

	private ArrayList<String> ReadFile(String path, boolean parser) {
		ArrayList<String> fitxer = new ArrayList<String>();
		FileReader fr;
		try {
			fr = new FileReader(path);
			BufferedReader bf = new BufferedReader(fr);
			String sCadena = null;
			while ((sCadena = bf.readLine()) != null) {
				String xcad = sCadena;
				if (parser == true) {
					xcad = this.ParseCadena(sCadena);
				}
				fitxer.add(xcad);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (parser == true) {
			return ParseComments(fitxer);
		} else {
			return fitxer;
		}
	}

	private ArrayList<String> ParseComments(ArrayList<String> file) {
		this.mComments = new HashMap<ArrayList<Integer>, String>();
		ArrayList<String> result = new ArrayList<String>();
		int linia = 1;
		ArrayList<Integer> startcom = new ArrayList<Integer>();
		for (String fline : file) {
			boolean comm = false;
			if (fline.length() > 0) {
				String comment = fline.substring(0, 3);
				String commenttxt = "";
				ArrayList<Integer> lin = new ArrayList<Integer>();
				if (comment.equals(this.mSimpleComment)) {
					comm = true;
					lin.add(linia - 1);
					commenttxt = fline.substring(3, fline.length());
					if (this.mComments.containsKey(lin)) {
						commenttxt = this.mComments.get(lin) + "<br/>"
								+ commenttxt;
					}
					this.mComments.put(lin, commenttxt);
				}
				if (comment.equals(this.mMultiCommentStart)) {
					comm = true;
					startcom.add(linia + 1);
				}
				if (comment.equals(this.mMultiCommentEnd)) {
					int last = startcom.size() - 1;
					comm = true;
					int start = startcom.get(last);
					// startcom.remove(last);
					lin.add(start);
					lin.add(linia);
					commenttxt = fline.substring(3, fline.length());
					if (this.mComments.containsKey(lin)) {
						commenttxt = this.mComments.get(lin) + "<br/>"
								+ commenttxt;
					}
					this.mComments.put(lin, commenttxt);
				}

			}
			if (comm == false) {
				String cad = "";
				String l = linia + "";
				String basic = "0";
				int basiclen = 6;
				for (int i = l.length(); i < basiclen; i++) {
					cad += basic;
				}
				cad += l + " " + fline;
				result.add(cad);
				linia++;
			}
		}
		return result;
	}

	public void printHash() {
		Iterator iterator = this.mComments.keySet().iterator();

		while (iterator.hasNext()) {
			String key = iterator.next().toString();
			String value = this.mComments.get(key);

			System.out.println("KEY." + key + ". VALUE." + value + ".");
		}
	}

	public ArrayList<String> GetComments(int line) {
		ArrayList<String> result = new ArrayList<String>();
		Iterator it = this.mComments.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry pairs = (Map.Entry) it.next();
			ArrayList<Integer> key = (ArrayList<Integer>) pairs.getKey();
			int min = key.get(0);
			int max = min;
			if (key.size() > 1) {
				max = key.get(1);
			}
			if (min > max) {
				int tmp = max;
				max = min;
				min = tmp;
			}
			if (line >= min && line <= max) {
				// System.out.println("MIN-Max:" + min + "-" + max);
				String l = "(" + min;
				if (min != max) {
					l += "-" + max;
				}
				l += ")";
				String txt = "<i>" + l + "</i> <b>" + pairs.getValue() + "</b>";
				result.add(txt);
			}
		}
		return result;
	}

	public ArrayList<String> GetCobolCode(String filename) {
		ArrayList<String> result = new ArrayList<String>();
		String path = this.mCobolFiles.get(filename);
		result = this.ReadFile(path);
		return result;
	}

	public ArrayList<String> GetJclCode(String filename) {
		ArrayList<String> result = new ArrayList<String>();
		String path = this.mJclFiles.get(filename);
		result = this.ReadFile(path);
		return result;
	}

	public ArrayList<String> GetJclFiles() {
		String path = this.mJclPath;
		File dir = new File(path);
		String[] children = dir.list();
		ArrayList<String> names = new ArrayList<String>();
		for (String cname : children) {
			String fpath = path + "\\" + cname;
			this.mJclFiles.put(cname, fpath);
			names.add(cname);
		}
		return names;
	}

	public ArrayList<HashMap<String, String>> GetCodes(String name) {
		ArrayList<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();
		if (this.mCodes.containsKey(name)) {
			Iterator iterator = this.mCodes.get(name).keySet().iterator();

			while (iterator.hasNext()) {
				String code = iterator.next().toString();
				String text = this.mCodes.get(name).get(code);
				int max = 80;
				String dots = "...";
				if (text.length() < max) {
					max = text.length();
					dots = "";
				}
				HashMap<String, String> r = new HashMap<String, String>();
				String res = text.substring(0, max).replace("<br/>", " ")
						+ dots;
				r.put(code, res);
				result.add(r);
			}
		}
		return result;
	}

	public String GetCodeInfo(String name, String num) {
		String result = "";
		if (this.mCodes.containsKey(name)) {
			HashMap<String, String> hash = this.mCodes.get(name);
			if (hash.containsKey(num)) {
				result = hash.get(num);
			}
		}
		return result;
	}

	public void WriteHistoryFile(String txt) {
		this.WriteFile(this.mHistoryPath, txt + "\n");
		this.GetHistory();
	}

	public ArrayList<ArrayList<String>> GetHistory() {
		String sep = this.mSeparator;
		ArrayList<String> file = this.ReadFile(this.mHistoryPath, false);
		ArrayList<ArrayList<String>> result = new ArrayList<ArrayList<String>>();
		for (String line : file) {
			ArrayList<String> r = new ArrayList<String>();
			String[] x = line.split(sep);
			for (int i = 0; i < x.length; i++) {
				r.add(x[i]);
			}
			result.add(r);
		}
		return result;
	}

	public void OpenCobolFile(String name) {
		if (this.mCobolFiles.containsKey(name)) {
			Runtime load = Runtime.getRuntime();
			// String path = this.mCobolFiles.get(name);
			try {
				load.exec("explorer.exe .\\" + this.mCobolPath);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public void OpenJclFile(String name) {
		// if (this.mJclPath.containsKey(name)) {
		Runtime load = Runtime.getRuntime();
		// String path = this.mCobolFiles.get(name);
		try {
			load.exec("explorer.exe .\\" + this.mJclPath);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// }
	}

	public void OpenCodeFile(String name) {
		// if (this.mCodePath.containsKey(name)) {
		Runtime load = Runtime.getRuntime();
		// String path = this.mCobolFiles.get(name);
		try {
			load.exec("explorer.exe .\\" + this.mCodePath);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// }
	}

}
